package jinyilw.common;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

public class ReflectTools
{
	private static volatile ConcurrentHashMap<String, Class<?>> classMap;

	private ReflectTools()
	{

	}

	public static ConcurrentHashMap<String, Class<?>> getClassMap()
	{
		if (classMap == null)
			synchronized (ReflectTools.class)
			{
				if (classMap == null)
					classMap = new ConcurrentHashMap<>();
			}
		return classMap;
	}

	/**
	 * 通过反射调用指定类名的指定静态无参方法.
	 */
	public static Object invokeStaticMethod(String theClassFullName,
			String methodName)
	{
		Class<?> theClass = getClass(theClassFullName);
		return invokeMethod(theClass, theClass, methodName, null);
	}
	/**
	 * 通过反射调用指定类名的指定静态方法.
	 */
	public static Object invokeStaticMethod(String theClassFullName,
			String methodName, Class<?>[] paramsType, Object[] paramsValue)
	{
		Class<?> theClass = getClass(theClassFullName);
		return invokeMethod(theClass, theClass, methodName, paramsType,
				paramsValue);
	}

	/**
	 * 通过反射调用指定Class对象的指定静态方法.
	 */
	public static Object invokeStaticMethod(Class<?> theClass, String methodName,
			Class<?>[] paramsType, Object[] paramsValue)
	{
		return invokeMethod(theClass, theClass, methodName, paramsType,
				paramsValue);
	}

	/**
	 * 通过反射调用指定Class对象的指定无参方法
	 */
	public static Object invokeMethod(String theClassFullName, Object theObject,
			String methodName)
	{
		return invokeMethod(getClass(theClassFullName), theObject, methodName,
				null);
	}

	/**
	 * 通过反射调用指定Class对象的指定方法
	 */
	public static Object invokeMethod(String theClassFullName, Object theObject,
			String methodName, Class<?>[] paramsType, Object[] paramsValue)
	{
		return invokeMethod(getClass(theClassFullName), theObject, methodName,
				paramsType, paramsValue);
	}

	/**
	 * 通过反射调用指定Class对象的指定方法（包括静态方法和实例方法）.
	 */
	public static Object invokeMethod(Class<?> theClass, Object theObject,
			String methodName, Class<?>[] paramsType, Object... paramsValue)
	{
		if (theClass == null || theObject == null || methodName == null)
			return null;
		Object ret = null;
		try
		{
			Method m = theClass.getMethod(methodName, paramsType);
			m.setAccessible(true);
			ret = m.invoke(theObject, paramsValue);
		} catch (Exception e)
		{
			System.err.println("通过反射调用方法" + theClass.getName() + "."
					+ methodName + "(" + Arrays.toString(paramsType) + ")失败\n"
					+ e);
		}
		return ret;
	}

	public static Class<?> getClass(String className)
	{
		if (classMap == null)
			getClassMap();
		if (classMap.containsKey(className))
			return classMap.get(className);
		try
		{
			Class<?> c = Class.forName(className);
			classMap.put(className, c);
			return c;
		} catch (Exception e)
		{
			System.err.println("通过反射获得" + className
					+ "的Class对象失败，您的JRE版本可能需要更新，" + e.getMessage());
			return null;
		}
	}

	public static String[] getAllFieldNames(Class<?> cls)
	{
		Field[] fields = cls.getDeclaredFields();
		String[] fieldNames = new String[fields.length];
		for (int i = 0; i < fields.length; i++)
			fieldNames[i] = fields[i].getName();
		return fieldNames;
	}

	public static List<String> getNoneStaticFieldNames(Class<?> cls)
	{
		Field[] fields = cls.getDeclaredFields();
		ArrayList<String> noneStaticFieldNames = new ArrayList<>();
		for (Field field : fields)
			if (!isStatic(field))
				noneStaticFieldNames.add(field.getName());
		return noneStaticFieldNames;
	}

	public static List<Field> getNoneStaticFields(Class<?> cls)
	{
		Field[] fields = cls.getDeclaredFields();
		ArrayList<Field> noneStaticFields = new ArrayList<>();
		for (Field field : fields)
			if (!isStatic(field))
				noneStaticFields.add(field);
		return noneStaticFields;
	}

	public static boolean isStatic(Field field)
	{
		int mod = field.getModifiers();
		return (mod & Modifier.STATIC) != 0;
	}
}
